home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / CITADEL BBS 'C' SRC / ROOMB.C < prev   
C/C++ Source or Header  |  1987-01-14  |  29KB  |  953 lines

  1. /************************************************************************/
  2. /*                roomb.c                 */
  3. /*        room code for Citadel bulletin board system        */
  4. /************************************************************************/
  5.  
  6. /************************************************************************/
  7. /*                History                 */
  8. /*                                    */
  9. /* 86Aug16 HAW    Kill history in here due to space problems.        */
  10. /* 85Jan16 JLS    Fix getText so console starting CR creates blank msg.    */
  11. /* 84Jun28 JLS    Enhancement: Creator of a room is listed in Aide>.    */
  12. /* 84Apr04 HAW    Start upgrade to BDS 1.50a.                */
  13. /* 83Feb26 CrT    bug in makeRoom when out of rooms fixed.        */
  14. /* 83Feb26 CrT    matchString made caseless, normalizeString()        */
  15. /* 83Feb26 CrT    "]" directory prompt, user name before prompts        */
  16. /* 82Dec06 CrT    2.00 release.                        */
  17. /* 82Nov02 CrT    Cleanup prior to V1.2 mods.                */
  18. /* 82Nov01 CrT    Proofread for CUG distribution.             */
  19. /* 82Mar27 dvm    conversion to v. 1.4 begun                */
  20. /* 82Mar25 dvm    conversion for TRS-80/Omikron test started        */
  21. /* 81Dec21 CrT    Log file...                        */
  22. /* 81Dec20 CrT    Messages...                        */
  23. /* 81Dec19 CrT    Rooms seem to be working...                */
  24. /* 81Dec12 CrT    Started.                        */
  25. /************************************************************************/
  26.  
  27. #include "ctdl.h"
  28.  
  29. /************************************************************************/
  30. /*                Contents                */
  31. /*                                    */
  32. /*    coreGetYesNo()        core for conGetYesNo() and getYesNo()    */
  33. /*    conGetYesNo()        prompts for a yes/no response from CON    */
  34. /*    editText()        handles the end-of-message-entry menu    */
  35. /*    findRoom()        find a free room            */
  36. /*    getNumber()        prompt user for a number, limited range */
  37. /*    getString()        read a string in from user        */
  38. /*    getText()        reads a message in from user        */
  39. /*    getYesNo()        prompts for a yes/no response        */
  40. /*    givePrompt()        gives usual "THISROOM>" prompt        */
  41. /*    # good_path()        gets subdirectory path from sysop    */
  42. /*    indexRooms()        build RAM index to ctdlroom.sys     */
  43. /*    initialArchive()    does initial archive of a room        */
  44. /*    makeRoom()        make new room via user dialogue     */
  45. /*    matchString()        search for given string         */
  46. /*    noteRoom()        enter room into RAM index        */
  47. /*    renameRoom()        sysop special to rename rooms        */
  48. /*    replaceString()     string-substitute for message entry    */
  49. /*                                    */
  50. /*    # -- operating system dependent function.            */
  51. /************************************************************************/
  52.  
  53. /************************************************************************/
  54. /*            External variable declarations in ROOMB.C        */
  55. /************************************************************************/
  56. char *public_str  = "Public";
  57. char *private_str = "Private";
  58. char *perm_str      = "Permanent";
  59. char *temp_str      = "Temporary";
  60. char exChar      = '?';
  61.  
  62. /************************************************************************/
  63. /*            External variable definitions for ROOMB.C        */
  64. /************************************************************************/
  65. extern struct aRoom    roomBuf;    /* Room buffer            */
  66. extern struct rTable    roomTab[];    /* RAM index            */
  67. extern FILE        *roomfl;    /* Room file descriptor     */
  68. extern struct config    cfg;        /* Other variables        */
  69. extern struct msgB    msgBuf;     /* Message buffer        */
  70. extern struct        msgB tempMess;    /* For held messages        */
  71. extern struct logBuffer logBuf;     /* Person buffer        */
  72. extern struct netBuffer netBuf;
  73. extern ulong        roomHiMsgs[];
  74. extern int        masterCount;
  75. extern int        thisRoom;    /* Current room         */
  76. extern char        remoteSysop;
  77. extern char        outFlag;    /* Output flag            */
  78. extern char        loggedIn;    /* Logged in?            */
  79. extern char        haveCarrier;    /* Have carrier?        */
  80. extern char        onConsole;    /* How about on Console?    */
  81. extern char        whichIO;    /* Where is I/O?        */
  82. extern char        debug;        /* Debug flag            */
  83. extern char        expert;     /* expert?            */
  84. extern char        *baseRoom;
  85. extern char        heldMessage;
  86. extern char        echo;
  87. extern char        echoChar;
  88. extern char        *confirm;
  89.  
  90. /************************************************************************/
  91. /*            External function definitions for ROOMB.C        */
  92. /************************************************************************/
  93. char *formRoom();
  94. char iChar();
  95. char getYesNo();
  96. char coreGetYesNo();
  97. char conGetYesNo();
  98. char toUpper();
  99. int  fread();
  100.  
  101. /************************************************************************/
  102. /*    conGetYesNo() prompts for a yes/no response from CONSOLE only    */
  103. /************************************************************************/
  104. char conGetYesNo(prompt)
  105. char *prompt;
  106. {
  107.     return coreGetYesNo(prompt, TRUE);
  108. }
  109.  
  110. /************************************************************************/
  111. /*    coreGetYesNo() prompts for a yes/no response given fn for echo    */
  112. /************************************************************************/
  113. char coreGetYesNo(prompt, consoleOnly)
  114. char *prompt;
  115. int  consoleOnly;
  116. {
  117.     int  toReturn;
  118.     char iChar(), getCh(), (*inputFn)();
  119.     int  printf(), mPrintf(), (*outputFn)();
  120. #define write_CR()    (!consoleOnly) ? doCR() : printf("\n")
  121.  
  122.     inputFn  = (consoleOnly) ? getCh  : iChar;
  123.     outputFn = (consoleOnly) ? printf : mPrintf;
  124.  
  125.     for (write_CR(), toReturn = ERROR; toReturn == ERROR && onLine(); ) {
  126.     outFlag = IMPERVIOUS;
  127.     (*outputFn)("%s? (Y/N): ", prompt);
  128.  
  129.     switch (toUpper((*inputFn)())) {
  130.     case 'Y': toReturn    = TRUE ;        break;
  131.     case 'N': toReturn    = FALSE;        break;
  132.     }
  133.     write_CR();
  134.     }
  135.     outFlag = OUTOK;
  136.     return   toReturn;
  137. }
  138.  
  139. /************************************************************************/
  140. /*    editText() handles the end-of-message-entry menu.        */
  141. /*    return TRUE  to save message to disk,                */
  142. /*           FALSE to abort message, and                */
  143. /*           ERROR if user decides to continue            */
  144. /************************************************************************/
  145. int editText(buf, lim)
  146. char *buf;
  147. int lim;
  148. {
  149.     extern char *ALL_LOCALS, *WRITE_LOCALS, *R_SH_MARK;
  150.  
  151.     do {
  152.     outFlag = IMPERVIOUS;
  153.     mPrintf("\n entry cmd: ");
  154.     switch (toUpper(iChar())) {
  155.     case 'A':
  156.         mPrintf("bort\n ");
  157.         if (getYesNo(confirm)) {
  158.         return FALSE;
  159.         }
  160.         break;
  161.     case 'C':
  162.         mPrintf("ontinue");
  163.         doCR();
  164.         return ERROR;
  165.     case 'P':
  166.         mPrintf("rint formatted\n ");
  167.         doCR();
  168.         outFlag = OUTOK;
  169.         mPrintf(   "   ");
  170.         printDate();
  171.         if (loggedIn)
  172.         mPrintf(" from %s", msgBuf.mbauth);
  173.         if (thisRoom == MAILROOM)
  174.         mPrintf(" to %s", msgBuf.mbto);
  175.         if (msgBuf.mbaddr[0] && strCmpU(msgBuf.mbaddr, R_SH_MARK) != 0)
  176.             mPrintf(" (on %s)", wrNetId(msgBuf.mbaddr));
  177.         if (msgBuf.mboname[0])
  178.             mPrintf(" @%s", msgBuf.mboname);
  179.         doCR();
  180.         mFormat(buf);
  181.         break;
  182.     case 'R':
  183.         mPrintf("eplace string\n ");
  184.         replaceString(buf, lim);
  185.         break;
  186.     case 'S':
  187.         mPrintf("ave buffer\n ");
  188.         return TRUE;
  189.         case 'H':
  190.             mPrintf("old message for later\n ");
  191.             if (heldMessage) {
  192.                 mPrintf("Message already being held!\n ");
  193.                 break;
  194.             }
  195.             mPrintf("Message held\n ");
  196.         movmem(&msgBuf, &tempMess, sizeof msgBuf);
  197.             heldMessage = TRUE;
  198.         return FALSE;
  199.     case '?':
  200.         tutorial("edit.mnu");
  201.         break;
  202.     default:
  203.         if (!expert) tutorial("edit.mnu");
  204.         else mPrintf(" ? (Type '?' for menu)\n \n");
  205.         break;
  206.     }
  207.     } while (onLine());
  208.     return FALSE;
  209. }
  210.  
  211. /************************************************************************/
  212. /*    findRoom() returns # of free room if possible, else ERROR    */
  213. /************************************************************************/
  214. int findRoom()
  215. {
  216.     int roomRover;
  217.  
  218.     for (roomRover = 0;  roomRover < MAXROOMS;    roomRover++) {
  219.     if (roomTab[roomRover].rtflags.INUSE == 0) return roomRover;
  220.     }
  221.     return ERROR;
  222. }
  223.  
  224. /************************************************************************/
  225. /*    getNumber() prompts for a number in (bottom, top) range.    */
  226. /************************************************************************/
  227. long getNumber(prompt, bottom, top)
  228. char  *prompt;
  229. long bottom;
  230. long top;
  231. {
  232.     long try;
  233.     long  atoi();
  234.     char numstring[NAMESIZE];
  235.  
  236.     do {
  237.     getString(prompt, numstring, NAMESIZE, FALSE, ECHO);
  238.     try    = atoi(numstring);
  239.     if (try < bottom)  mPrintf("Sorry, must be at least %ld\n", bottom);
  240.     if (try > top    )  mPrintf("Sorry, must be no more than %ld\n", top);
  241.     } while ((try < bottom ||  try > top) && onLine());
  242.     return  (long) try;
  243. }
  244.  
  245. /************************************************************************/
  246. /*    getString() gets a string from the user.            */
  247. /************************************************************************/
  248. getString(prompt, buf, lim, QuestIsSpecial, doEcho)
  249. char *prompt;
  250. char *buf;
  251. char doEcho;
  252. int  lim;    /* max # chars to read */
  253. char QuestIsSpecial;    /* Return immediately on '?' input?        */
  254. {
  255.     char c, oldEcho;
  256.     int  i;
  257.  
  258.     outFlag = IMPERVIOUS;
  259.  
  260.     if (strLen(prompt) > 0) {
  261.     doCR();
  262.     mPrintf("Enter %s\n : ", prompt, lim);
  263.     }
  264.  
  265.     oldEcho = echo;
  266.     if (!doEcho) {
  267.     echo     = NEITHER;
  268.     echoChar = 'X';
  269.     }
  270.  
  271.     i    = 0;
  272.     while (
  273.      c = iChar(),
  274.  
  275.      c      != NEWLINE
  276.      && i      <  lim
  277.      && onLine()
  278.     ) {
  279.     outFlag = OUTOK;
  280.  
  281.     /* handle delete chars: */
  282.     if (c == BACKSPACE) {
  283.         oChar(' ');
  284.         oChar(BACKSPACE);
  285.         if (i > 0) i--;
  286.         else  {
  287.         oChar(' ');
  288.         oChar(BELL);
  289.         }
  290.     } else     buf[i++] = c;
  291.  
  292.     if (i >= lim) {
  293.         oChar(BELL);
  294.         oChar(BACKSPACE); i--;
  295.     }
  296.  
  297.     /* kludge to return immediately on single '?': */
  298.     if (QuestIsSpecial && *buf == exChar)    {
  299.         doCR();
  300.         break;
  301.     }
  302.     }
  303.     echo    = oldEcho;
  304.     buf[i]  = '\0';
  305. }
  306.  
  307. /************************************************************************/
  308. /*    getText() reads a message from the user             */
  309. /*    Returns TRUE if user decides to save it, else FALSE        */
  310. /************************************************************************/
  311. char getText(uploading)
  312. char uploading;
  313. {
  314. #ifdef NEED_VISIBLE
  315.     char visible();
  316. #endif
  317.     extern char *R_SH_MARK;
  318.     char c, *buf, beeped = FALSE;
  319.     int  i, toReturn, lim, putBufChar();
  320.  
  321.     buf = msgBuf.mbtext;
  322.     buf[-1] = NEWLINE;
  323.  
  324.     if (!uploading) {
  325.     if (!expert) {
  326.         tutorial("entry.blb");
  327.         mPrintf("Enter message (end with empty line)");
  328.     }
  329.     outFlag = OUTOK;
  330.     doCR();
  331.     mPrintf("   ");
  332.     printDate();
  333.     if (loggedIn)          mPrintf("from %s", msgBuf.mbauth);
  334.     if (thisRoom == MAILROOM) mPrintf(" to %s", msgBuf.mbto);
  335.     if (msgBuf.mbaddr[0] &&
  336.             strCmpU(msgBuf.mbaddr, R_SH_MARK) != SAMESTRING)
  337.                   mPrintf(" (on %s)", wrNetId(msgBuf.mbaddr));
  338.     if (msgBuf.mboname[0])      mPrintf(    " @%s", msgBuf.mboname);
  339.     doCR();
  340.  
  341.     if (msgBuf.mbtext[0]) {
  342.         outFlag = OUTOK;
  343.         mFormat(buf);
  344.         outFlag = OUTOK;
  345.         doCR();
  346.     }
  347.     outFlag = OUTOK;
  348.     lim    = MAXTEXT - 1;
  349.     }
  350.     else {
  351.     if (!expert) tutorial("wcupload.blb");
  352.     if (!getYesNo("Ready for WC transfer"))
  353.         return FALSE;
  354.     masterCount = 0;
  355.     if (!readFile(putBufChar))
  356.         return FALSE;
  357.     }
  358.  
  359.     do {
  360.     i = strLen(buf);
  361.     if (!uploading)
  362.         while (
  363.         !(
  364.             (c=iChar()) == NEWLINE   &&
  365.             (buf[i-1] == NEWLINE || i == 0)
  366.         )
  367.         && i < lim
  368.         && onLine()
  369.         ) {
  370.         if (c != BACKSPACE) {
  371.             if (c != 0) buf[i++]   = c;
  372.             if (i > MAXTEXT - 80 && !beeped) {
  373.             beeped = TRUE;
  374.             oChar(BELL);
  375.             }
  376.         }
  377.         else {
  378.              /* handle delete chars: */
  379.             oChar(' ');
  380.             oChar(BACKSPACE);
  381.             if (i > 0 && buf[i-1] != NEWLINE)    i--;
  382.             else                oChar(BELL);
  383.         }
  384.  
  385.         buf[i] = 0x00;            /* null to terminate message     */
  386.  
  387.         if (i == lim)    mPrintf(" buffer overflow\n ");
  388.         }
  389.  
  390.     toReturn = editText(buf, lim);
  391.     uploading = FALSE;
  392.     } while ((toReturn == ERROR)  &&  onLine());
  393.     if (toReturn == TRUE) {        /* Filter null messages     */
  394.     toReturn = FALSE;
  395.     for (i = 0; buf[i] != 0 && !toReturn; i++)
  396.         toReturn = (buf[i] > ' ' && buf[i] < 127);
  397.     }
  398.     return  toReturn;
  399. }
  400.  
  401. /************************************************************************/
  402. /*    getYesNo() prompts for a yes/no response            */
  403. /************************************************************************/
  404. char getYesNo(prompt)
  405. char *prompt;
  406. {
  407.     return coreGetYesNo(prompt, FALSE);
  408. }
  409.  
  410. /************************************************************************/
  411. /*    givePrompt() prints the usual "CURRENTROOM>" prompt.        */
  412. /************************************************************************/
  413. givePrompt()
  414. {
  415.     outFlag = IMPERVIOUS;
  416.     doCR();
  417.     if (loggedIn)   printf("(%s)\n", logBuf.lbname);
  418.     if (!expert) {
  419.     mPrintf("<G>oto%s%s <H>elp",
  420.      (thisRoom == MAILROOM || loggedIn || cfg.unlogReadOk)  ? " <N>ew"     : "",
  421.      (thisRoom == MAILROOM || loggedIn || cfg.unlogEnterOk) ? " <E>nter" : "");
  422.     doCR();
  423.     }
  424.  
  425.     mPrintf("%s ", formRoom(thisRoom, FALSE));
  426.  
  427.     if (strCmp(roomBuf.rbname, roomTab[thisRoom].rtname) != SAMESTRING) {
  428.     printf("thisRoom=%d, rbname=-%s-, rtname=-%s-\n", thisRoom,
  429. roomBuf.rbname, roomTab[thisRoom].rtname);
  430.     crashout("Dependent variables mismatch!");
  431.     }
  432.     outFlag = OUTOK;
  433. }
  434.  
  435. /************************************************************************/
  436. /*    good_path() Gets a valid path from the sysop. Drive should be    */
  437. /*            set already.                    */
  438. /************************************************************************/
  439. good_path(buffer, size)
  440. char *buffer;
  441. int  size;
  442. {
  443.     char *cd, *gcdir();
  444.     char gooddir;
  445.  
  446.     cd = gcdir("");
  447.     buffer[0] = '\\';
  448.     do {
  449.     mPrintf("\n Path: \\");
  450.     getString("", buffer+1, size - 1, FALSE, ECHO, FALSE);
  451.     gooddir = ((chdir(buffer) != EOF) || buffer[1] == '?');
  452.     if (!gooddir) printf("Directory not found.\n");
  453.     } while (!gooddir);
  454.     chdir(cd);
  455.     free(cd);
  456. }
  457.  
  458. /************************************************************************/
  459. /*    indexRooms() -- build RAM index to CTDLROOM.SYS, by CITADEL, to */
  460. /*    delete empty rooms.                        */
  461. /************************************************************************/
  462. indexRooms()
  463. {
  464.     int  goodRoom, m, slot;
  465.  
  466.     for (slot = 0;  slot < MAXROOMS;  slot++) {
  467.     if (roomTab[slot].rtflags.INUSE == 1) {
  468.         goodRoom = FALSE;
  469.         if (roomTab[slot].rtlastMessage > cfg.oldest ||
  470.         roomTab[slot].rtflags.PERMROOM == 1) {
  471.         goodRoom    = TRUE;
  472.         }
  473.  
  474.         if (!goodRoom) {
  475.         getRoom(slot);
  476.         roomBuf.rbflags.INUSE     = 0;
  477.         roomBuf.rbflags.MSDOSDIR = 0;
  478.         roomBuf.rbflags.PERMROOM = 0;
  479.         roomBuf.rbflags.INUSE     = 0;
  480.         putRoom(slot);
  481.         strCat(msgBuf.mbtext, roomBuf.rbname);
  482.         strCat(msgBuf.mbtext, "> ");
  483.         noteRoom();
  484.         }
  485.     }
  486.     }
  487. }
  488.  
  489. /************************************************************************/
  490. /*    makeRoom() constructs a new room via dialogue with user.    */
  491. /************************************************************************/
  492. makeRoom()
  493. {
  494.     char *nm[NAMESIZE];
  495.     char *oldName[NAMESIZE];
  496.     int  i;
  497.  
  498.     /* update lastMessage for current room: */
  499.     logBuf.lbgen[thisRoom]    = roomBuf.rbgen << GENSHIFT;
  500.  
  501.     strCpy(oldName, roomBuf.rbname);
  502.     if ((thisRoom = findRoom()) == ERROR) {
  503.     indexRooms();    /* try and reclaim an empty room    */
  504.     if ((thisRoom = findRoom()) == ERROR) {
  505.         mPrintf(" ?no room, sorry");
  506.         /* may have reclaimed old room, so: */
  507.         if (roomExists(oldName) == ERROR)    strCpy(oldName, baseRoom);
  508.         getRoom(roomExists(oldName));
  509.         return;
  510.     }
  511.     }
  512.  
  513.     getNormStr("name for new room", nm, NAMESIZE, ECHO);
  514.     if (strLen(nm) == 0) {
  515.     if (roomExists(oldName) == ERROR)   strCpy(oldName, baseRoom);
  516.     getRoom(roomExists(oldName));
  517.     return ;
  518.     }
  519.  
  520.     if (roomExists(nm) >= 0) {
  521.     mPrintf(" A '%s' already exists.\n", nm);
  522.     /* may have reclaimed old room, so: */
  523.     if (roomExists(oldName) == ERROR)   strCpy(oldName, baseRoom);
  524.     getRoom(roomExists(oldName));
  525.     return;
  526.     }
  527.     if (!expert)   tutorial("newroom.blb");
  528.  
  529.     roomBuf.rbflags.INUSE    = TRUE;
  530.     roomBuf.rbflags.PERMROOM =
  531.     roomBuf.rbflags.MSDOSDIR =
  532.     roomBuf.rbflags.UPLOAD   =
  533.     roomBuf.rbflags.DOWNLOAD =
  534.     roomBuf.rbflags.SHARED   =
  535.     roomBuf.rbflags.ARCHIVE  =
  536.     roomBuf.rbflags.rflag3   =
  537.     roomBuf.rbflags.rflag4   =
  538.     roomBuf.rbflags.rflag5   =
  539.     roomBuf.rbflags.rflag6   =
  540.     roomBuf.rbflags.rflag7   =
  541.     roomBuf.rbflags.rflag8   =
  542.     roomBuf.rbflags.rflag9   =
  543.     roomBuf.rbflags.rflag10  =
  544.     roomBuf.rbflags.rflag11  =
  545.     roomBuf.rbflags.rflag12  = FALSE;
  546.  
  547.     if (getYesNo(" Make room public")) roomBuf.rbflags.PUBLIC = TRUE;
  548.     else                   roomBuf.rbflags.PUBLIC = FALSE;
  549.  
  550.     mPrintf("'%s', a %s room",
  551.     nm,
  552.     roomBuf.rbflags.PUBLIC == 1  ?    "public"  :  "private"
  553.     );
  554.  
  555.     if(!getYesNo("Install it")) {
  556.     /* may have reclaimed old room, so: */
  557.     if (roomExists(oldName) == ERROR)   strCpy(oldName, baseRoom);
  558.     getRoom(roomExists(oldName));
  559.     return;
  560.     }
  561.  
  562.     strCpy(roomBuf.rbname, nm);
  563.     for (i = 0;  i < MSGSPERRM;  i++) {
  564.     roomBuf.msg[i].rbmsgNo     = 0l;     /* mark all slots empty */
  565.     roomBuf.msg[i].rbmsgLoc  = 0 ;
  566.     }
  567.     roomBuf.rbgen = (roomTab[thisRoom].rtgen + 1) % MAXGEN;
  568.  
  569.     noteRoom();             /* index new room    */
  570.     putRoom(thisRoom);
  571.  
  572.     /* update logBuf: */
  573.     logBuf.lbgen[thisRoom]    = roomBuf.rbgen << GENSHIFT;
  574.     sPrintf(msgBuf.mbtext, "%s> created by %s", nm, logBuf.lbname);
  575.     aideMessage(FALSE);
  576.     roomHiMsgs[thisRoom] = 0l;
  577. }
  578.  
  579. /************************************************************************/
  580. /*    matchString() searches for match to given string.  Runs backward*/
  581. /*    through buffer so we get most recent error first.        */
  582. /*    Returns loc of match, else ERROR                */
  583. /************************************************************************/
  584. char *matchString(buf, pattern, bufEnd)
  585. char *buf, *pattern, *bufEnd;
  586. {
  587.     char *loc, *pc1, *pc2;
  588.     char foundIt;
  589.  
  590.     for (loc = bufEnd, foundIt = FALSE;  !foundIt && --loc >= buf;) {
  591.     for (pc1 = pattern, pc2 = loc,    foundIt = TRUE ;  *pc1 && foundIt;) {
  592.         if (! (toLower(*pc1++) == toLower(*pc2++)))   foundIt = FALSE;
  593.     }
  594.     }
  595.  
  596.     return   foundIt  ?  loc  :  NULL;
  597. }
  598.  
  599. /************************************************************************/
  600. /*    getNormStr() gets a string and deletes leading            */
  601. /*                      & trailing blanks etc.    */
  602. /************************************************************************/
  603. getNormStr(prompt, s, size, doEcho)
  604. char *s, *prompt;
  605. char doEcho;
  606. int  size;
  607. {
  608.     char *pc;
  609.  
  610.     getString(prompt, s, size, FALSE, doEcho);
  611.     pc = s;
  612.  
  613.     /* find end of string   */
  614.     while (*pc)   {
  615.     if (*pc < ' ')     *pc = ' ';   /* zap tabs etc... */
  616.     pc++;
  617.     }
  618.  
  619.     /* no trailing spaces: */
  620.     while (pc>s  &&  isSpace(*(pc-1))) pc--;
  621.     *pc = '\0';
  622.  
  623.     /* no leading spaces: */
  624.     while (*s == ' ') {
  625.     for (pc=s;  *pc;  pc++)    *pc = *(pc+1);
  626.     }
  627.  
  628.     /* no double blanks */
  629.     for (;  *s;)   {
  630.     if (*s == ' '    &&   *(s+1) == ' ')   {
  631.         for (pc=s;    *pc;  pc++)    *pc = *(pc+1);
  632.     }
  633.     else s++;
  634.     }
  635. }
  636.  
  637. /************************************************************************/
  638. /*    noteRoom() -- enter room into RAM index array.            */
  639. /************************************************************************/
  640. noteRoom()
  641. {
  642.     int   i;
  643.     ulong last;
  644.  
  645.     last = 0l;
  646.     for (i = 0;  i < MSGSPERROOM;  i++)  {
  647.     if (roomBuf.msg[i].rbmsgNo > last) {
  648.         last = roomBuf.msg[i].rbmsgNo;
  649.     }
  650.     }
  651.     roomTab[thisRoom].rtlastMessage = last         ;
  652.     strCpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
  653.     roomTab[thisRoom].rtgen        = roomBuf.rbgen  ;
  654.     movmem(&roomBuf.rbflags, &roomTab[thisRoom].rtflags,
  655.                          sizeof roomBuf.rbflags);
  656. }
  657.  
  658. /************************************************************************/
  659. /*    renameRoom() is sysop special fn                */
  660. /*    Returns:    TRUE on success else FALSE            */
  661. /************************************************************************/
  662. renameRoom()
  663. {
  664.     char nm[NAMESIZE];
  665.     char buffer[200];
  666.     char c, goodOne, wasDirectory, wasArchive, wasShare;
  667.     int  r;
  668.  
  669.     if (                /* clearer than "thisRoom <= AIDEROOM"*/
  670.     thisRoom == LOBBY
  671.     ||
  672.     thisRoom == MAILROOM
  673.     ||
  674.     thisRoom == AIDEROOM
  675.     ) {
  676.     mPrintf("? -- may not edit this room.\n ");
  677.     return FALSE;
  678.     }
  679.  
  680.     wasDirectory = roomBuf.rbflags.MSDOSDIR;
  681.     wasArchive     = roomBuf.rbflags.ARCHIVE;
  682.     wasShare     = roomBuf.rbflags.SHARED;
  683.  
  684.     formatSummary(buffer);
  685.     sPrintf(msgBuf.mbtext, "%s, formerly ", formRoom(thisRoom, FALSE));
  686.     strCat(msgBuf.mbtext, buffer);
  687.  
  688.     mPrintf("\n %s is a %s\n ", formRoom(thisRoom, FALSE), buffer);
  689.  
  690.     if (!getYesNo("Edit room"))   return FALSE;
  691.  
  692.     if (getYesNo("Change name"))   {
  693.     getNormStr("new room name", nm, NAMESIZE, ECHO);
  694.     r = roomExists(nm);
  695.     if (r >= 0  &&    r != thisRoom) {
  696.          mPrintf("A %s exists already!\n", nm);
  697.     } else {
  698.         strCpy(roomBuf.rbname, nm);   /* also in room itself  */
  699.     }
  700.     }
  701.     roomBuf.rbflags.INUSE = TRUE;
  702.  
  703.     if (getYesNo("Public room"))    {
  704.     roomBuf.rbflags.PUBLIC = TRUE;
  705.     } else {
  706.     roomBuf.rbflags.PUBLIC = FALSE;
  707.     if (getYesNo("Cause non-aide users to forget room")) {
  708.         roomBuf.rbgen    = (roomBuf.rbgen +1) % MAXGEN;
  709.         logBuf.lbgen[thisRoom] = (logBuf.lbgen[thisRoom] & CALLMASK) +
  710.                            (roomBuf.rbgen << GENSHIFT);
  711. roomTab[thisRoom].rtgen = roomBuf.rbgen;
  712.     }
  713.     }
  714.  
  715.     if (!onConsole && !remoteSysop) roomBuf.rbflags.MSDOSDIR = wasDirectory;
  716.     else if (getYesNo("Directory room")) {
  717.     roomBuf.rbflags.MSDOSDIR = TRUE;
  718.  
  719.     for (goodOne = FALSE;  !goodOne;  )   {
  720.         getString("disk", nm, NAMESIZE, FALSE, ECHO);
  721.         c        = toUpper(nm[0]);
  722.         if (c>='A'    && c<='Z') {
  723.         roomBuf.rbdisk        = c - 'A';
  724.         goodOne         = TRUE;
  725.         } else mPrintf("?");
  726.     }
  727.     setSpace(roomBuf.rbdisk, "");
  728.  
  729.     for (goodOne = FALSE;  !goodOne;  )   {
  730.         getString("directory (empty entry means use current directory)",
  731.                                nm, 9, FALSE, ECHO);
  732.         if (index(nm, ' ') != NULL)
  733.         mPrintf("No spaces in directory names!");
  734.         else if (index(nm, '\\') != NULL)
  735.         mPrintf("No '\\'s in directory names!");
  736.         else if (strLen(nm) == 0) {
  737.         goodOne = TRUE;
  738.         strCpy(roomBuf.rbdirname, nm);
  739.         }
  740.         else if (chdir(nm) != EOF) {
  741.         mPrintf("%s exists. ", nm);
  742.         goodOne = getYesNo("Use it");
  743.         chdir("..");
  744.         if (goodOne)
  745.             strCpy(roomBuf.rbdirname, nm);
  746.         }
  747.         else {
  748.         mPrintf("%s does not exist. ", nm);
  749.         goodOne = getYesNo("Create");
  750.         if (goodOne) {
  751.             if (mkdir(nm) == EOF) {
  752.             mPrintf("?ERROR CREATING!");
  753.             roomBuf.rbflags.MSDOSDIR = FALSE;
  754.             }
  755.             else strCpy(roomBuf.rbdirname, nm);
  756.         }
  757.         }
  758.     }
  759.     setSpace(cfg.homeDisk, "");
  760.     }
  761.     else
  762.     roomBuf.rbflags.MSDOSDIR = FALSE;
  763.  
  764.     if (roomBuf.rbflags.MSDOSDIR == TRUE || getYesNo("permanent")) {
  765.     roomBuf.rbflags.PERMROOM = TRUE;
  766.     }
  767.     else
  768.     roomBuf.rbflags.PERMROOM = FALSE;
  769.  
  770.     if ((onConsole || remoteSysop)) {
  771.     if (roomBuf.rbflags.MSDOSDIR == TRUE) {
  772.         roomBuf.rbflags.UPLOAD   = getYesNo("Are uploads allowed");
  773.         roomBuf.rbflags.DOWNLOAD = getYesNo("Are downloads allowed");
  774.         if (!roomBuf.rbflags.UPLOAD && !roomBuf.rbflags.DOWNLOAD)
  775.         mPrintf("You're strange.\n ");
  776.     }
  777.  
  778.     if ((roomBuf.rbflags.ARCHIVE = getYesNo("Should room be archived"))) {
  779.         if (!wasArchive) {
  780.         getString("filename", buffer, 198, FALSE, ECHO);
  781.         if (!addArchiveList(thisRoom, buffer))
  782.             roomBuf.rbflags.ARCHIVE = 0;
  783.         else
  784.             initialArchive(buffer);
  785.         }
  786.     }
  787.  
  788.     if (cfg.netParticipant &&
  789.           (roomBuf.rbflags.SHARED = getYesNo("Network room"))) {
  790.         mPrintf("%s (Empty line to end)", wasShared ?
  791.             "Systems to add to network list for this room" :
  792.             "Systems to network this room with");
  793.         doCR();
  794.         do {
  795.         mPrintf(": ");
  796.         getNormStr("", nm, NAMESIZE, ECHO);
  797.         if (strLen(nm) != 0) addToList(nm);
  798.         } while (strLen(nm) != 0);
  799.     }
  800.     }
  801.  
  802.     noteRoom();
  803.     putRoom(thisRoom);
  804.  
  805.     sPrintf(msgBuf.mbtext+strLen(msgBuf.mbtext), ", has been edited to %s, ",
  806.            formRoom(thisRoom, FALSE));
  807.     formatSummary(msgBuf.mbtext + strLen(msgBuf.mbtext));
  808.     sPrintf(msgBuf.mbtext+strLen(msgBuf.mbtext), ", by %s.", logBuf.lbname);
  809.  
  810.     aideMessage(FALSE);
  811.     return TRUE;
  812. }
  813.  
  814. /************************************************************************/
  815. /*    formatSummary() formats a summary of the current room        */
  816. /************************************************************************/
  817. formatSummary(buffer)
  818. char *buffer;
  819. {
  820.     sPrintf(buffer,"a %s, %s, %sarchived %sdirectory room",
  821.         roomBuf.rbflags.PUBLIC   == 1 ? public_str : private_str,
  822.         roomBuf.rbflags.PERMROOM == 1 ? perm_str   : temp_str,
  823.         roomBuf.rbflags.ARCHIVE  == 1 ? "" : "non",
  824.         roomBuf.rbflags.MSDOSDIR == 1 ? "" : "non");
  825.     if (roomBuf.rbflags.MSDOSDIR == 1) {
  826.     sPrintf(buffer+strLen(buffer), " (drive %c, directory %s, ",
  827.             'A'+roomBuf.rbdisk,
  828. (strLen(roomBuf.rbdirname) == 0 ? "is current directory" : roomBuf.rbdirname));
  829.     sPrintf(buffer+strLen(buffer), "allows %suploads, %sdownloads)",
  830.         (roomBuf.rbflags.UPLOAD)   ? "" : "no ",
  831.         (roomBuf.rbflags.DOWNLOAD) ? "" : "no ");
  832.     }
  833. }
  834.  
  835. /************************************************************************/
  836. /*    replaceString() corrects typos in message entry         */
  837. /************************************************************************/
  838. replaceString(buf, lim)
  839. char *buf;
  840. int  lim;
  841. {
  842.     char oldString[2*SECTSIZE];
  843.     char newString[2*SECTSIZE];
  844.     char *loc, *textEnd;
  845.     char *pc;
  846.     int  incr, length;
  847.     char *matchString();
  848.                           /* find terminal null */
  849.     for (textEnd = buf, length = 0;  *textEnd;    length++, textEnd++);
  850.  
  851.     getString("string",      oldString, (2*SECTSIZE), FALSE, ECHO);
  852.     if ((loc=matchString(buf, oldString, textEnd)) == NULL) {
  853.     mPrintf("?not found.\n ");
  854.     return;
  855.     }
  856.  
  857.     getString("replacement", newString, (2*SECTSIZE), FALSE, ECHO);
  858.     if ( (strLen(newString)-strLen(oldString))    >=  lim - length) {
  859.     mPrintf("?Overflow!\n ");
  860.     return;
  861.     }
  862.  
  863.     /* delete old string: */
  864.     for (pc=loc, incr=strLen(oldString);  *pc=*(pc+incr);  pc++);
  865.     textEnd -= incr;
  866.  
  867.     /* make room for new string: */
  868.     for (pc=textEnd, incr=strLen(newString);  pc>=loc;    pc--) {
  869.     *(pc+incr) = *pc;
  870.     }
  871.  
  872.     /* insert new string: */
  873.     for (pc=newString;    *pc;  *loc++ = *pc++);
  874. }
  875.  
  876. /************************************************************************/
  877. /*    initialArchive() Does initial archive of a room         */
  878. /************************************************************************/
  879. initialArchive(fn)
  880. char *fn;
  881. {
  882.     int msgRover;
  883.     ulong number;
  884.  
  885.     strCpy(tempMess.mbtext, msgBuf.mbtext);
  886.     mPrintf("Doing the initial archive\n ");
  887.     for (msgRover = 0; msgRover < MSGSPERROOM; msgRover++) {
  888.     number = roomBuf.msg[msgRover].rbmsgNo;
  889.     if (number > cfg.oldest && number < cfg.newest) {
  890.         msgToDisk(fn, roomBuf.msg[msgRover].rbmsgNo,
  891.               roomBuf.msg[msgRover].rbmsgLoc);
  892.         mPrintf("%ld\n ", roomBuf.msg[msgRover].rbmsgNo);
  893.     }
  894.     }
  895.     strCpy(msgBuf.mbtext, tempMess.mbtext);
  896. }
  897.  
  898. /************************************************************************/
  899. /*    addToList() Adds a system to a room networking list        */
  900. /************************************************************************/
  901. addToList(name)
  902. char *name;
  903. {
  904.     int slot, i, temp, gen;
  905.     extern struct nodeRoomsTab *sharedRooms;
  906.  
  907.     if (name[0] == '?') {
  908.     writeNet(FALSE);
  909.     return ;
  910.     }
  911.  
  912.     if ((slot = searchNameNet(name)) == ERROR) {
  913.     mPrintf("No '%s' known", name);
  914.     doCR();
  915.     return;
  916.     }
  917.  
  918.     getNet(slot);
  919.  
  920.     for (i = 0; i < SHARED_ROOMS; i++) {
  921.     if ((netBuf.netRooms[i].srgen & 0x8000) != 0) { /* Salvage attempt */
  922.         temp = netBuf.netRooms[i].srslot & 0x7fff;
  923.         gen  = netBuf.netRooms[i].srgen & 0x7fff;
  924.  
  925.         if (temp == thisRoom && gen == roomBuf.rbgen) {
  926.         mPrintf("Already netting this room with %s", name);
  927.         doCR();
  928.         return ;
  929.         }
  930.  
  931.         if (roomTab[temp].rtgen != gen ||    /* No longer exists!    */
  932.         roomTab[temp].rtflags.SHARED == 0) {    /* Not netting    */
  933.         break;
  934.         }
  935.     }
  936.     else
  937.         break;
  938.     }
  939.  
  940.     if (i == SHARED_ROOMS) {
  941.     mPrintf("Sorry, already sharing %d rooms with %s", SHARED_ROOMS, name);
  942.     return;
  943.     }
  944.  
  945.     netBuf.netRooms[i].srslot    = thisRoom;
  946.     netBuf.netRooms[i].lastMess = 0l;
  947.     netBuf.netRooms[i].srgen    = roomBuf.rbgen + (unsigned) 0x8000;
  948.     copy_array(netBuf.netRooms, sharedRooms[slot].rooms);
  949.  
  950. dumpNodeRoom(TRUE);
  951.     putNet(slot);
  952. }
  953.